this._childFocused(actor);
});
// Standard hack for ClutterBinLayout
- this._grid.actor.x_expand = true;
+ this._grid.x_expand = true;
this._items = {};
this._allItems = [];
},
_doSpringAnimation(animationDirection) {
- this._grid.actor.opacity = 255;
+ this._grid.opacity = 255;
this._grid.animateSpring(animationDirection,
Main.overview.getShowAppsButton());
},
}
if (animationDirection == IconGrid.AnimationDirection.IN) {
- let id = this._grid.actor.connect('paint', () => {
- this._grid.actor.disconnect(id);
+ let id = this._grid.connect('paint', () => {
+ this._grid.disconnect(id);
this._doSpringAnimation(animationDirection);
});
} else {
animateSwitch(animationDirection) {
Tweener.removeTweens(this.actor);
- Tweener.removeTweens(this._grid.actor);
+ Tweener.removeTweens(this._grid);
let params = { time: VIEWS_SWITCH_TIME,
transition: 'easeOutQuad' };
params.onComplete = () => { this.actor.hide(); };
}
- Tweener.addTween(this._grid.actor, params);
+ Tweener.addTween(this._grid, params);
}
});
Signals.addSignalMethods(BaseAppView.prototype);
let box = new St.BoxLayout({ vertical: true });
this._grid.currentPage = 0;
- this._stack.add_actor(this._grid.actor);
+ this._stack.add_actor(this._grid);
this._eventBlocker = new St.Widget({ x_expand: true, y_expand: true });
this._stack.add_actor(this._eventBlocker);
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
box = this._scrollView.get_theme_node().get_content_box(box);
- box = this._grid.actor.get_theme_node().get_content_box(box);
+ box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
let oldNPages = this._grid.nPages();
y_align: Clutter.ActorAlign.CENTER,
y_expand: true });
- this._grid.actor.y_expand = true;
+ this._grid.y_expand = true;
- this.actor.add_actor(this._grid.actor);
+ this.actor.add_actor(this._grid);
this.actor.add_actor(this._noFrequentAppsLabel);
this._noFrequentAppsLabel.hide();
box.x2 = width;
box.y2 = height;
box = this.actor.get_theme_node().get_content_box(box);
- box = this._grid.actor.get_theme_node().get_content_box(box);
+ box = this._grid.get_theme_node().get_content_box(box);
let availWidth = box.x2 - box.x1;
let availHeight = box.y2 - box.y1;
this._grid.adaptToSize(availWidth, availHeight);
this.parent(null, null);
// If it not expand, the parent doesn't take into account its preferred_width when allocating
// the second time it allocates, so we apply the "Standard hack for ClutterBinLayout"
- this._grid.actor.x_expand = true;
+ this._grid.x_expand = true;
this.actor = new St.ScrollView({ overlay_scrollbars: true });
this.actor.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC);
let scrollableContainer = new St.BoxLayout({ vertical: true, reactive: true });
- scrollableContainer.add_actor(this._grid.actor);
+ scrollableContainer.add_actor(this._grid);
this.actor.add_actor(scrollableContainer);
let action = new Clutter.PanAction({ interpolate: true });
_updatePopupSize() {
// StWidget delays style calculation until needed, make sure we use the correct values
- this.view._grid.actor.ensure_style();
+ this.view._grid.ensure_style();
let offsetForEachSide = Math.ceil((this._popup.getOffset(St.Side.TOP) +
this._popup.getOffset(St.Side.BOTTOM) -
var IconGrid = new Lang.Class({
Name: 'IconGrid',
+ Extends: St.Widget,
+ Signals: {'animation-done': {},
+ 'child-focused': { param_types: [Clutter.Actor.$gtype]} },
_init(params) {
+ this.parent({ style_class: 'icon-grid',
+ y_align: Clutter.ActorAlign.START });
+
+ this.actor = this;
+
params = Params.parse(params, { rowLimit: null,
columnLimit: null,
minRows: 1,
this.rightPadding = 0;
this.leftPadding = 0;
- this.actor = new St.BoxLayout({ style_class: 'icon-grid',
- vertical: true });
this._items = [];
this._clonesAnimating = [];
// Pulled from CSS, but hardcode some defaults here
this._spacing = 0;
this._hItemSize = this._vItemSize = ICON_SIZE;
this._fixedHItemSize = this._fixedVItemSize = undefined;
- this._grid = new Shell.GenericContainer();
- this.actor.add(this._grid, { expand: true, y_align: St.Align.START });
- this.actor.connect('style-changed', this._onStyleChanged.bind(this));
+ this.connect('style-changed', this._onStyleChanged.bind(this));
// Cancel animations when hiding the overview, to avoid icons
// swarming into the void ...
- this.actor.connect('notify::mapped', () => {
- if (!this.actor.mapped)
+ this.connect('notify::mapped', () => {
+ if (!this.mapped)
this._cancelAnimation();
});
- this._grid.connect('get-preferred-width', this._getPreferredWidth.bind(this));
- this._grid.connect('get-preferred-height', this._getPreferredHeight.bind(this));
- this._grid.connect('allocate', this._allocate.bind(this));
- this._grid.connect('actor-added', this._childAdded.bind(this));
- this._grid.connect('actor-removed', this._childRemoved.bind(this));
+ this.connect('actor-added', this._childAdded.bind(this));
+ this.connect('actor-removed', this._childRemoved.bind(this));
},
_keyFocusIn(actor) {
child.disconnect(child._iconGridKeyFocusInId);
},
- _getPreferredWidth(grid, forHeight, alloc) {
+ vfunc_get_preferred_width(forHeight) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
- return;
+ return [0, 0];
- let nChildren = this._grid.get_n_children();
+ let nChildren = this.get_n_children();
let nColumns = this._colLimit ? Math.min(this._colLimit,
nChildren)
: nChildren;
// Kind of a lie, but not really an issue right now. If
// we wanted to support some sort of hidden/overflow that would
// need higher level design
- alloc.min_size = this._getHItemSize() + this.leftPadding + this.rightPadding;
- alloc.natural_size = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
+ let minSize = this._getHItemSize() + this.leftPadding + this.rightPadding;
+ let natSize = nColumns * this._getHItemSize() + totalSpacing + this.leftPadding + this.rightPadding;
+
+ return this.get_theme_node().adjust_preferred_width(minSize, natSize);
},
_getVisibleChildren() {
- return this._grid.get_children().filter(actor => actor.visible);
+ return this.get_children().filter(actor => actor.visible);
},
- _getPreferredHeight(grid, forWidth, alloc) {
+ vfunc_get_preferred_height(forWidth) {
if (this._fillParent)
// Ignore all size requests of children and request a size of 0;
// later we'll allocate as many children as fit the parent
- return;
+ return [0, 0];
+ let themeNode = this.get_theme_node();
let children = this._getVisibleChildren();
let nColumns;
+
+ forWidth = themeNode.adjust_for_width(forWidth);
+
if (forWidth < 0)
nColumns = children.length;
else
nRows = Math.min(nRows, this._rowLimit);
let totalSpacing = Math.max(0, nRows - 1) * this._getSpacing();
let height = nRows * this._getVItemSize() + totalSpacing + this.topPadding + this.bottomPadding;
- alloc.min_size = height;
- alloc.natural_size = height;
+
+ return themeNode.adjust_preferred_height(height, height);
},
- _allocate(grid, box, flags) {
+ vfunc_allocate(box, flags) {
+ this.set_allocation(box, flags);
+
+ let themeNode = this.get_theme_node();
+ box = themeNode.get_content_box(box);
+
if (this._fillParent) {
// Reset the passed in box to fill the parent
- let parentBox = this.actor.get_parent().allocation;
- let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
- box = this._grid.get_theme_node().get_content_box(gridBox);
+ let parentBox = this.get_parent().allocation;
+ let gridBox = themeNode.get_content_box(parentBox);
+ box = themeNode.get_content_box(gridBox);
}
let children = this._getVisibleChildren();
if (this._rowLimit && rowIndex >= this._rowLimit ||
this._fillParent && childBox.y2 > availHeight - this.bottomPadding) {
- this._grid.set_skip_paint(children[i], true);
+ children[i]._skipPaint = true;
} else {
children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+ children[i]._skipPaint = false;
}
columnIndex++;
}
},
+ vfunc_paint() {
+ this.paint_background();
+
+ this.get_children().forEach(c => {
+ if (!c._skipPaint)
+ c.paint();
+ });
+ },
+
+ vfunc_pick(color) {
+ this.parent(color);
+
+ this.get_children().forEach(c => {
+ if (!c._skipPaint)
+ c.paint();
+ });
+ },
+
+ vfunc_get_paint_volume(paintVolume) {
+ // Setting the paint volume does not make sense when we don't have
+ // any allocation
+ if (!this.has_allocation())
+ return false;
+
+ let themeNode = this.get_theme_node();
+ let allocationBox = this.get_allocation_box();
+ let paintBox = themeNode.get_paint_box(allocationBox);
+
+ let origin = new Clutter.Vertex();
+ origin.x = paintBox.x1 - allocationBox.x1;
+ origin.y = paintBox.y1 - allocationBox.y1;
+ origin.z = 0.0;
+
+ paintVolume.set_origin(origin);
+ paintVolume.set_width(paintBox.x2 - paintBox.x1);
+ paintVolume.set_height(paintBox.y2 - paintBox.y1);
+
+ if (this.get_clip_to_allocation())
+ return true;
+
+ for (let child = this.get_first_child();
+ child != null;
+ child = child.get_next_sibling()) {
+
+ if (!child.visible)
+ continue;
+
+ if (child._skipPaint)
+ continue;
+
+ let childVolume = child.get_transformed_paint_volume(this);
+ if (!childVolume)
+ return false
+
+ paintVolume.union(childVolume);
+ }
+
+ return true;
+ },
+
/**
* Intended to be override by subclasses if they need a different
* set of items to be animated.
},
_onStyleChanged() {
- let themeNode = this.actor.get_theme_node();
+ let themeNode = this.get_theme_node();
this._spacing = themeNode.get_length('spacing');
this._hItemSize = themeNode.get_length('-shell-grid-horizontal-item-size') || ICON_SIZE;
this._vItemSize = themeNode.get_length('-shell-grid-vertical-item-size') || ICON_SIZE;
- this._grid.queue_relayout();
+ this.queue_relayout();
},
nRows(forWidth) {
removeAll() {
this._items = [];
- this._grid.remove_all_children();
+ this.remove_all_children();
},
destroyAll() {
this._items = [];
- this._grid.destroy_all_children();
+ this.destroy_all_children();
},
addItem(item, index) {
this._items.push(item);
if (index !== undefined)
- this._grid.insert_child_at_index(item.actor, index);
+ this.insert_child_at_index(item.actor, index);
else
- this._grid.add_actor(item.actor);
+ this.add_actor(item.actor);
},
removeItem(item) {
- this._grid.remove_child(item.actor);
+ this.remove_child(item.actor);
},
getItemAtIndex(index) {
- return this._grid.get_child_at_index(index);
+ return this.get_child_at_index(index);
},
visibleItemsCount() {
- return this._grid.get_n_children() - this._grid.get_n_skip_paint();
+ return this.get_children().filter(c => !c._skipPaint).length;
},
setSpacing(spacing) {
}
}
});
-Signals.addSignalMethods(IconGrid.prototype);
var PaginatedIconGrid = new Lang.Class({
Name: 'PaginatedIconGrid',
Extends: IconGrid,
+ Signals: {'space-opened': {},
+ 'space-closed': {} },
_init(params) {
this.parent(params);
this._childrenPerPage = 0;
},
- _getPreferredHeight(grid, forWidth, alloc) {
- alloc.min_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
- alloc.natural_size = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
+ vfunc_get_preferred_height(forWidth) {
+ let height = (this._availableHeightPerPageForItems() + this.bottomPadding + this.topPadding) * this._nPages + this._spaceBetweenPages * this._nPages;
+ return [height, height];
},
- _allocate(grid, box, flags) {
+ vfunc_allocate(box, flags) {
if (this._childrenPerPage == 0)
log('computePages() must be called before allocate(); pagination will not work.');
+ this.set_allocation(box, flags);
+
if (this._fillParent) {
// Reset the passed in box to fill the parent
- let parentBox = this.actor.get_parent().allocation;
- let gridBox = this.actor.get_theme_node().get_content_box(parentBox);
- box = this._grid.get_theme_node().get_content_box(gridBox);
+ let parentBox = this.get_parent().allocation;
+ let gridBox = this.get_theme_node().get_content_box(parentBox);
+ box = this.get_theme_node().get_content_box(gridBox);
}
let children = this._getVisibleChildren();
let availWidth = box.x2 - box.x1;
for (let i = 0; i < children.length; i++) {
let childBox = this._calculateChildBox(children[i], x, y, box);
children[i].allocate(childBox, flags);
- this._grid.set_skip_paint(children[i], false);
+ children[i]._skipPaint = false;
columnIndex++;
if (columnIndex == nColumns) {
}
}
});
-Signals.addSignalMethods(PaginatedIconGrid.prototype);